package lk.icta.common.service.impl;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.lang.GeoLocation;
import com.drew.lang.Rational;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.GpsDirectory;
import lk.icta.common.AppConstants;
import lk.icta.common.dto.GeoPoint;
import lk.icta.common.entity.Document;
import lk.icta.common.service.GISService;
import lk.icta.user.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

public class GISServiceImpl implements GISService {

    private static final Logger logger = LoggerFactory.getLogger(GISServiceImpl.class);

    public GISServiceImpl() {
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public GeoPoint getGeoLocation(User user, String filePath) {
        GeoPoint geoInformation = null;
        try {
		
		    File file = new File(filePath);
			
			//1st method
			GeoLocation gl = getMetadata(file);
            if (gl != null) {
                logger.debug("latitude ---------------------------- {}", gl.getLatitude());
                logger.debug("longitude -------------------------- {}", gl.getLongitude());
            }


            try {
                // logger.debug("-------------------image extractor3");
                Metadata metadata = ImageMetadataReader.readMetadata(file);
                //  logger.debug("-------------------image extractor4");

                /* for (Directory directory : metadata.getDirectories()) {
                    for (Tag tag : directory.getTags()) {
                        logger.debug("-------------------meta data ---- {}", tag);
                    }
                }*/


                // obtain the Exif directory
                Directory directory = metadata.getDirectory(ExifSubIFDDirectory.class);
                if (directory != null) {
                    for (Tag tag : directory.getTags()) {
                        logger.debug("-------------------meta data - Exif directory---- {}", tag);
                    }
                }


                //2nd method - good
                //GpsDirectory gpsDirectory = metadata.getDirectory(GpsDirectory.class);
                GpsDirectory gpsDirectory = metadata.getDirectory(GpsDirectory.class);
                if (gpsDirectory != null) {
                    logger.debug("-------------------image extractor5 {} ", gpsDirectory);

                    GeoLocation geoLocation = gpsDirectory.getGeoLocation();
                    for (Tag tag : gpsDirectory.getTags()) {
                        logger.debug("-------------------meta data GPS ---- {}", tag);
                    }

                    if (geoLocation != null) {
                        DecimalFormat geoDecimalFormat = new DecimalFormat(AppConstants.GEO_DECIMAL_FORMAT_STRING,
                                new DecimalFormatSymbols(Locale.ENGLISH));

                        geoInformation =
                                new GeoPoint(geoDecimalFormat.format(geoLocation.getLongitude()),
                                        geoDecimalFormat.format(geoLocation.getLatitude()));

                        logger.debug("latitude ---------------------------- {}", geoLocation.getLatitude());
                        logger.debug("longitude -------------------------- {}", geoLocation.getLongitude());
                    }

                    // query the tag's value
                    //Date date = directory.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL);
                    // double longitude = gpsDirectory.getDoubleObject(GpsDirectory.TAG_GPS_LONGITUDE);
                    // double latitute = gpsDirectory.getDoubleObject(GpsDirectory.TAG_GPS_LATITUDE);

                    //3rd method   - old

                    double lat = 0.0;
                    double lon = 0.0;
                    double alt = 0.0;
                    boolean error = false;

                    logger.debug("-------------------image extractor6");
                    // logger.debug("date -------------------{} ", date);

                    ////////////////////////////
                    Rational latpart[] = gpsDirectory.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
                    Rational lonpart[] = gpsDirectory.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
                    String northing = gpsDirectory.getString(GpsDirectory.TAG_GPS_LATITUDE_REF);
                    String easting = gpsDirectory.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF);

                    double latsign = 1.0d;
                    if (northing.equalsIgnoreCase("S")) {
                        latsign = -1.0d;
                    }
                    double lonsign = 1.0d;
                    if (easting.equalsIgnoreCase("W")) {
                        lonsign = -1.0d;
                    }
                    lat = (Math.abs(latpart[0].doubleValue()) + latpart[1].doubleValue() / 60.0d + latpart[2].doubleValue() / 3600.0d) * latsign;
                    lon = (Math.abs(lonpart[0].doubleValue()) + lonpart[1].doubleValue() / 60.0d + lonpart[2].doubleValue() / 3600.0d) * lonsign;

                    if (Double.isNaN(lat) || Double.isNaN(lon)) {
                        logger.debug("longitude and latitude -------------------------- NAN");
                        error = true;
                    } else {
                        logger.debug("latitude ---------------------------- {}", lat);
                        logger.debug("longitude -------------------------- {}", lon);
                    }
                }


            } catch (ImageProcessingException ip) {
                ip.printStackTrace();
            } catch (IOException me) {
                me.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return geoInformation;
    }

    public static GeoLocation getMetadata(File file) {
        GeoLocation gl = null;

        try {
            //File file = new File(filename);
            Metadata metadata = ImageMetadataReader.readMetadata(file);

            for (Directory directory : metadata.getDirectories()) {
                 logger.debug("-------------------------directory--------------{}", directory.getName());

                if (directory instanceof GpsDirectory) {
                      logger.debug("-------------------------GPS directory 1--------------");
                    GpsDirectory gpsd = (GpsDirectory) directory;
                     logger.debug("-------------------------GPS directory 2--------------");
                    gl = gpsd.getGeoLocation();
                     logger.debug("-------------------------GPS directory 3--------------");
                    logger.debug("-------------------------GPS directory 3--------------{}", gl.getLatitude());
                    logger.debug("-------------------------GPS directory 3--------------{}", gl.getLongitude());
                }
            }

        } catch (ImageProcessingException ex) {
            ex.printStackTrace();
        } catch (IOException io) {
            io.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        }
        return gl;
    }

}
